function seq = nrLowPAPRS(u,varargin)
%nrLowPAPRS Low-PAPR sequence
%   SEQ = nrLowPAPRS(U,V,ALPHA,M) returns the type 1 low peak to average
%   power ratio (low-PAPR) sequence(s) SEQ of length M, given the group
%   number(s) U, sequence number(s) V within the group, and cyclic shift(s)
%   ALPHA, as defined by TS 38.211, Section 5.2.2. SEQ is of size
%   M-by-NumALPHA-by-NumU-by-NumV. NumALPHA is the number of elements in
%   ALPHA. NumU is the number of elements in U. NumV is the number of
%   elements in V.
%
%   The type 1 low-PAPR sequences are derived from the base sequences. The
%   base sequences are divided into 30 sequence groups where each group is
%   identified by the group number U (0...29). Each group consists of one
%   base sequence (V equal to 0) when the length M is less than 72 and two
%   base sequences (V equal to 0 or 1) otherwise. Different phase rotations
%   corresponding to different cyclic shifts ALPHA, can be applied to the
%   base sequence to give multiple low-PAPR sequences. These sequences are
%   used in generation of uplink (UL) demodulation reference signals
%   (DM-RS), sounding reference signals (SRS), and physical uplink control
%   channel (PUCCH) format 0 and 1 symbols.
%
%   SEQ = nrLowPAPRS(U,CINIT,M) returns the type 2 low peak to average
%   power ratio (low-PAPR) sequence(s) SEQ of length M, given the group
%   number(s) U, and sequence initialization(s) CINIT, as defined by
%   TS 38.211, Section 5.2.3. SEQ is of size M-by-NumCINIT-by-NumU. NumCINIT
%   is the number of elements in CINIT. NumU is the number of elements in U.
%
%   The type 2 low-PAPR sequences are derived from fast Fourier transform
%   (FFT) operation of the base sequences. The base sequences are divided
%   into 30 sequence groups, where each group is identified by the group
%   number U (0...29). For a sequence length greater than or equal to 30,
%   base sequences are obtained by performing the pi/2-BPSK modulation for
%   the pseudo random binary sequence (PRBS). Similarly, for sequence
%   length equal to one of {12, 18, 24}, the base sequence is obtained by
%   performing the pi/2-BPSK modulation for the bits selected on the basis
%   of group number and sequence length. For sequence length equal to 6,
%   the base sequence is the complex exponential of pi/8 rotated phase
%   values, obtained by group number. These low-PAPR sequences are used in
%   generation of DM-RS for physical uplink shared channel (PUSCH), PUCCH
%   format 3 and 4, when configured with Release 16 DM-RS transform
%   precoding.
%
%   Note that the function considers the length of the sequence as input,
%   so the bandwidth transmission parameters m and delta, required for
%   calculation of the sequence length are not used here.
%
%   SEQ = nrLowPAPRS(U,V,ALPHA,M,NAME,VALUE) and
%   SEQ = nrLowPAPRS(U,CINIT,M,NAME,VALUE) specifies an additional option
%   as a NAME,VALUE pair to allow control over the format of the sequence:
%
%   'OutputDataType' - 'double' for double precision (default)
%                      'single' for single precision
%
%   Example 1:
%   % Generate a 36 length type 1 low-PAPR sequence with group number as 9,
%   % sequence number 0 and cyclic shift as 2*pi.
%
%   u = 9;
%   v = 0;
%   alpha = 2*pi;
%   m = 36;
%   seq = nrLowPAPRS(u,v,alpha,m);
%
%   Example 2:
%   % Generate a type 1 low-PAPR sequence of single data type with sequence
%   % length as 72, group number as 15, sequence number as 1 and cyclic
%   % shift as 0.
%
%   u = 15;
%   v = 1;
%   alpha = 0;
%   m = 72;
%   seq = nrLowPAPRS(u,v,alpha,m,'OutputDataType','single');
%
%   Example 3:
%   % Generate type 1 low-PAPR sequences of length 12 for a vector of phase
%   % rotations [pi/2, pi] with base sequence defined by group number 23
%   % and sequence number 0.
%
%   u = 23;
%   v = 0;
%   alpha = [pi/2, pi];
%   m = 12;
%   seq = nrLowPAPRS(u,v,alpha,m);
%
%   Example 4:
%   % Generate 36 length type 2 low-PAPR sequence for a vector of sequence
%   % initializations [10, 325] with group number set to 9.
%
%   u = 9;
%   cinit = [10, 325];
%   m = 36;
%   seq = nrLowPAPRS(u,cinit,m);
%
%   See also nrPRBS, nrPUCCH0, nrPUCCH1.

% Copyright 2018-2020 The MathWorks, Inc.

%#codegen

    coder.extrinsic('nr5g.internal.parseOptions');

    narginchk (3,6);

    % Validate input U
    fcnName = 'nrLowPAPRS';
    validateattributes(u,{'numeric'},...
        {'nonempty','vector','integer','nonnegative','<=',29},fcnName,'U');
    numU = numel(u); % Number of elements in input U

    % Get the low-PAPR sequence type 1 or 2, based on number of inputs
    if any(nargin == [4 6])
        % U,V,ALPHA,M) or
        % U,V,ALPHA,M,NAME,VALUE)
        % Type 1 low-PAPR sequence

        % Parse and validate inputs
        v = varargin{1};
        alpha = varargin{2};
        m = varargin{3};
        validateattributes(v, {'numeric'},...
            {'nonempty','vector','integer'},fcnName,'V');
        validateattributes(alpha,{'numeric'},...
            {'nonempty','vector','nonnegative','finite'},fcnName,'ALPHA');
        validateattributes(m,{'numeric'},...
            {'scalar','integer','nonnegative'},fcnName,'M');
        nvarg = 4;

        % Cast the inputs to double
        uD = double(u);
        vD = reshape(double(v),1,[]);
        alphaD = reshape(double(alpha),1,[]);
        mD = double(m);
        numV = numel(vD);

        % Check if all the entries in sequence number is either 0 or 1
        coder.internal.errorIf(~(all((vD == 0) | (vD == 1))),...
            'nr5g:nrLowPAPRS:InvalidV');

        % Check if sequence length is a multiple of 6, when sequence length
        % is less than 36
        coder.internal.errorIf(((mD/6)~=fix(mD/6)) && (mD < 36),...
            'nr5g:nrLowPAPRS:InvalidM',mD);

        % Check the sequence number based on the sequence length
        coder.internal.errorIf((mD < 72) && any(vD),...
            'nr5g:nrLowPAPRS:InvalidCombinationMV',mD);

        % Get the base sequence
        lpsMat = complex(zeros(mD,numel(alphaD),numU,numV));
        for vIndex = 1:numV
            for uIndex = 1:numU
                nIndex = (0:mD-1)';
                if ~mD
                    baseSeq = zeros(0,1);
                elseif mD < 30
                    % Get the phase values based on sequence length and
                    % group number
                    phi = getPhiType1(uD(uIndex),mD);
                    baseSeq = exp(1j.*phi.*pi/4);
                elseif mD == 30
                    baseSeq = exp(-1j*pi*(uD(uIndex)+1)*(nIndex+1).*(nIndex+2)/31);
                else
                    % Get the largest prime number less than the length of
                    % sequence
                    n = primes(mD-1);
                    nzc = n(end);
                    qBar = nzc*(uD(uIndex)+1)/31;
                    q = floor(qBar+0.5) + vD(vIndex)*(-1)^floor(2*qBar);
                    % Get the index values modulo nzc
                    mIndex = [0:nzc-1 0:mD-nzc-1]';
                    % Get the cyclic extended Zadoff-Chu sequence
                    baseSeq = exp(-1j*pi*q*mIndex.*(mIndex+1)/nzc);
                end

                % Get the type 1 low-PAPR sequence(s) from the base sequence
                lps = exp(1j*nIndex*alphaD).*repmat(baseSeq,1,length(alphaD));

                % Assign the type 1 low-PAPR sequence(s) of different
                % cyclic shift(s) for each group number and sequence number
                lpsMat(:,:,uIndex,vIndex) = lps;
            end
        end
    else
        % U,CINIT,M) or
        % U,CINIT,M,NAME,VALUE)
        % Type 2 low-PAPR sequence

        % Parse and validate inputs
        cinit = varargin{1};
        m = varargin{2};
        validateattributes(cinit,{'numeric'},...
            {'vector','nonnegative','integer'},fcnName,'CINIT');
        validateattributes(m,{'numeric'},...
            {'scalar','integer','nonnegative'},fcnName,'M');
        nvarg = 3;

        % Check if sequence length is a multiple of 6, when sequence length
        % is less than 36
        mD = double(m);
        coder.internal.errorIf(((mD/6)~=fix(mD/6)) && (mD < 36),...
            'nr5g:nrLowPAPRS:InvalidM',mD);

        % Get the base sequence
        numCINIT = numel(cinit);
        lpsMat = complex(zeros(mD,numCINIT,numU));
        nIndex = (0:mD-1)';
        for cIndex = 1:numCINIT
            for uIndex = 1:numU
                if mD == 0
                    baseSeq = zeros(0,1);
                elseif mD == 6
                    % Get the phase values based on group number
                    phi = getPhiType2(u(uIndex));
                    baseSeq = exp(1j.*phi.*pi/8);
                else
                    if mD < 30
                        % Get the bit sequence based on group number and
                        % sequence length
                        bits = getBits(u(uIndex),mD);
                    else % mD greater than or equal to 30
                        % Get the binary sequence based on sequence
                        % initialization and length
                        bits = double(nrPRBS(cinit(cIndex),mD));
                    end
                    % Get the base sequence by applying pi/2-BPSK
                    % modulation for the binary sequence
                    baseSeq = (1/sqrt(2))*(exp(1j.*(pi/2).*mod(nIndex,2)).*...
                        ((1-2*bits)+1j*(1-2*bits)));
                end

                % Get the type 2 low-PAPR sequence from the base sequence
                lps = fft(baseSeq)/sqrt(mD);

                % Assign the type 2 low-PAPR sequence for each sequence
                % initialization and group number
                lpsMat(:,cIndex,uIndex) = lps;
            end
        end
    end

    % Apply options
    if nargin > 4
        opts = coder.const(nr5g.internal.parseOptions(fcnName,...
            {'OutputDataType'},varargin{nvarg:end}));
        seq = cast(lpsMat,opts.OutputDataType);
    else
        seq = lpsMat;
    end

end

function phi = getPhiType1(u,m)
%   PHI = getPhiType1(U,M) provides the phase values, PHI, to be applied
%   for generating the type 1 base sequence based on the group number U and
%   the sequence length M, as stated in the TS 38.211 Section 5.2.2.

    % Get the table of phase values based on the length M
    if m == 6 % Table 5.2.2.2-1
        phiTable = [-3  -1   3   3  -1  -3; ...
                    -3   3  -1  -1   3  -3; ...
                    -3  -3  -3   3   1  -3; ...
                     1   1   1   3  -1  -3; ...
                     1   1   1  -3  -1   3; ...
                    -3   1  -1  -3  -3  -3; ...
                    -3   1   3  -3  -3  -3; ...
                    -3  -1   1  -3   1  -1; ...
                    -3  -1  -3   1  -3  -3; ...
                    -3  -3   1  -3   3  -3; ...
                    -3   1   3   1  -3  -3; ...
                    -3  -1  -3   1   1  -3; ...
                     1   1   3  -1  -3   3; ...
                     1   1   3   3  -1   3; ...
                     1   1   1  -3   3  -1; ...
                     1   1   1  -1   3  -3; ...
                    -3  -1  -1  -1   3  -1; ...
                    -3  -3  -1   1  -1  -3; ...
                    -3  -3  -3   1  -3  -1; ...
                    -3   1   1  -3  -1  -3; ...
                    -3   3  -3   1   1  -3; ...
                    -3   1  -3  -3  -3  -1; ...
                     1   1  -3   3   1   3; ...
                     1   1  -3  -3   1  -3; ...
                     1   1   3  -1   3   3; ...
                     1   1  -3   1   3   3; ...
                     1   1  -1  -1   3  -1; ...
                     1   1  -1   3  -1  -1; ...
                     1   1  -1   3  -3  -1; ...
                     1   1  -3   1  -1  -1];
    elseif m == 12 % Table 5.2.2.2-2
        phiTable = [-3   1  -3  -3  -3   3  -3  -1   1   1   1  -3; ...
                    -3   3   1  -3   1   3  -1  -1   1   3   3   3; ...
                    -3   3   3   1  -3   3  -1   1   3  -3   3  -3; ...
                    -3  -3  -1   3   3   3  -3   3  -3   1  -1  -3; ...
                    -3  -1  -1   1   3   1   1  -1   1  -1  -3   1; ...
                    -3  -3   3   1  -3  -3  -3  -1   3  -1   1   3; ...
                     1  -1   3  -1  -1  -1  -3  -1   1   1   1  -3; ...
                    -1  -3   3  -1  -3  -3  -3  -1   1  -1   1  -3; ...
                    -3  -1   3   1  -3  -1  -3   3   1   3   3   1; ...
                    -3  -1  -1  -3  -3  -1  -3   3   1   3  -1  -3; ...
                    -3   3  -3   3   3  -3  -1  -1   3   3   1  -3; ...
                    -3  -1  -3  -1  -1  -3   3   3  -1  -1   1  -3; ...
                    -3  -1   3  -3  -3  -1  -3   1  -1  -3   3   3; ...
                    -3   1  -1  -1   3   3  -3  -1  -1  -3  -1  -3; ...
                     1   3  -3   1   3   3   3   1  -1   1  -1   3; ...
                    -3   1   3  -1  -1  -3  -3  -1  -1   3   1  -3; ...
                    -1  -1  -1  -1   1  -3  -1   3   3  -1  -3   1; ...
                    -1   1   1  -1   1   3   3  -1  -1  -3   1  -3; ...
                    -3   1   3   3  -1  -1  -3   3   3  -3   3  -3; ...
                    -3  -3   3  -3  -1   3   3   3  -1  -3   1  -3; ...
                     3   1   3   1   3  -3  -1   1   3   1  -1  -3; ...
                    -3   3   1   3  -3   1   1   1   1   3  -3   3; ...
                    -3   3   3   3  -1  -3  -3  -1  -3   1   3  -3; ...
                     3  -1  -3   3  -3  -1   3   3   3  -3  -1  -3; ...
                    -3  -1   1  -3   1   3   3   3  -1  -3   3   3; ...
                    -3   3   1  -1   3   3  -3   1  -1   1  -1   1; ...
                    -1   1   3  -3   1  -1   1  -1  -1  -3   1  -1; ...
                    -3  -3   3   3   3  -3  -1   1  -3   3   1  -3; ...
                     1  -1   3   1   1  -1  -1  -1   1   3  -3   1; ...
                    -3   3  -3   3  -3  -3   3  -1  -1   1   3  -3];
    elseif m == 18 % Table 5.2.2.2-3
        phiTable = [-1   3  -1  -3   3   1  -3  -1   3  -3  -1  -1   1   1   1  -1  -1  -1; ...
                     3  -3   3  -1   1   3  -3  -1  -3  -3  -1  -3   3   1  -1   3  -3   3; ...
                    -3   3   1  -1  -1   3  -3  -1   1   1   1   1   1  -1   3  -1  -3  -1; ...
                    -3  -3   3   3   3   1  -3   1   3   3   1  -3  -3   3  -1  -3  -1   1; ...
                     1   1  -1  -1  -3  -1   1  -3  -3  -3   1  -3  -1  -1   1  -1   3   1; ...
                     3  -3   1   1   3  -1   1  -1  -1  -3   1   1  -1   3   3  -3   3  -1; ...
                    -3   3  -1   1   3   1  -3  -1   1   1  -3   1   3   3  -1  -3  -3  -3; ...
                     1   1  -3   3   3   1   3  -3   3  -1   1   1  -1   1  -3  -3  -1   3; ...
                    -3   1  -3  -3   1  -3  -3   3   1  -3  -1  -3  -3  -3  -1   1   1   3; ...
                     3  -1   3   1  -3  -3  -1   1  -3  -3   3   3   3   1   3  -3   3  -3; ...
                    -3  -3  -3   1  -3   3   1   1   3  -3  -3   1   3  -1   3  -3  -3   3; ...
                    -3  -3   3   3   3  -1  -1  -3  -1  -1  -1   3   1  -3  -3  -1   3  -1; ...
                    -3  -1  -3  -3   1   1  -1  -3  -1  -3  -1  -1   3   3  -1   3   1   3; ...
                     1   1  -3  -3  -3  -3   1   3  -3   3   3   1  -3  -1   3  -1  -3   1; ...
                    -3   3  -1  -3  -1  -3   1   1  -3  -3  -1  -1   3  -3   1   3   1   1; ...
                     3   1  -3   1  -3   3   3  -1  -3  -3  -1  -3  -3   3  -3  -1   1   3; ...
                    -3  -1  -3  -1  -3   1   3  -3  -1   3   3   3   1  -1  -3   3  -1  -3; ...
                    -3  -1   3   3  -1   3  -1  -3  -1   1  -1  -3  -1  -1  -1   3   3   1; ...
                    -3   1  -3  -1  -1   3   1  -3  -3  -3  -1  -3  -3   1   1   1  -1  -1; ...
                     3   3   3  -3  -1  -3  -1   3  -1   1  -1  -3   1  -3  -3  -1   3   3; ...
                    -3   1   1  -3   1   1   3  -3  -1  -3  -1   3  -3   3  -1  -1  -1  -3; ...
                     1  -3  -1  -3   3   3  -1  -3   1  -3  -3  -1  -3  -1   1   3   3   3; ...
                    -3  -3   1  -1  -1   1   1  -3  -1   3   3   3   3  -1   3   1   3   1; ...
                     3  -1  -3   1  -3  -3  -3   3   3  -1   1  -3  -1   3   1   1   3   3; ...
                     3  -1  -1   1  -3  -1  -3  -1  -3  -3  -1  -3   1   1   1  -3  -3   3; ...
                    -3  -3   1  -3   3   3   3  -1   3   1   1  -3  -3  -3   3  -3  -1  -1; ...
                    -3  -1  -1  -3   1  -3   3  -1  -1  -3   3   3  -3  -1   3  -1  -1  -1; ...
                    -3  -3   3   3  -3   1   3  -1  -3   1  -1  -3   3  -3  -1  -1  -1   3; ...
                    -1  -3   1  -3  -3  -3   1   1   3   3  -3   3   3  -3  -1   3  -3   1; ...
                    -3   3   1  -1  -1  -1  -1   1  -1   3   3  -3  -1   1   3  -1   3  -1];
    else % m is equal to 24. Table 5.2.2.2-4
        phiTable = [-1  -3   3  -1   3   1   3  -1   1  -3  -1  -3  -1   1   3  -3  -1  -3   3   3   3  -3  -3  -3; ...
                    -1  -3   3   1   1  -3   1  -3  -3   1  -3  -1  -1   3  -3   3   3   3  -3   1   3   3  -3  -3; ...
                    -1  -3  -3   1  -1  -1  -3   1   3  -1  -3  -1  -1  -3   1   1   3   1  -3  -1  -1   3  -3  -3; ...
                     1  -3   3  -1  -3  -1   3   3   1  -1   1   1   3  -3  -1  -3  -3  -3  -1   3  -3  -1  -3  -3; ...
                    -1   3  -3  -3  -1   3  -1  -1   1   3   1   3  -1  -1  -3   1   3   1  -1  -3   1  -1  -3  -3; ...
                    -3  -1   1  -3  -3   1   1  -3   3  -1  -1  -3   1   3   1  -1  -3  -1  -3   1  -3  -3  -3  -3; ...
                    -3   3   1   3  -1   1  -3   1  -3   1  -1  -3  -1  -3  -3  -3  -3  -1  -1  -1   1   1  -3  -3; ...
                    -3   1   3  -1   1  -1   3  -3   3  -1  -3  -1  -3   3  -1  -1  -1  -3  -1  -1  -3   3   3  -3; ...
                    -3   1  -3   3  -1  -1  -1  -3   3   1  -1  -3  -1   1   3  -1   1  -1   1  -3  -3  -3  -3  -3; ...
                     1   1  -1  -3  -1   1   1  -3   1  -1   1  -3   3  -3  -3   3  -1  -3   1   3  -3   1  -3  -3; ...
                    -3  -3  -3  -1   3  -3   3   1   3   1  -3  -1  -1  -3   1   1   3   1  -1  -3   3   1   3  -3; ...
                    -3   3  -1   3   1  -1  -1  -1   3   3   1   1   1   3   3   1  -3  -3  -1   1  -3   1   3  -3; ...
                     3  -3   3  -1  -3   1   3   1  -1  -1  -3  -1   3  -3   3  -1  -1   3   3  -3  -3   3  -3  -3; ...
                    -3   3  -1   3  -1   3   3   1   1  -3   1   3  -3   3  -3  -3  -1   1   3  -3  -1  -1  -3  -3; ...
                    -3   1  -3  -1  -1   3   1   3  -3   1  -1   3   3  -1  -3   3  -3  -1  -1  -3  -3  -3   3  -3; ...
                    -3  -1  -1  -3   1  -3  -3  -1  -1   3  -1   1  -1   3   1  -3  -1   3   1   1  -1  -1  -3  -3; ...
                    -3  -3   1  -1   3   3  -3  -1   1  -1  -1   1   1  -1  -1   3  -3   1  -3   1  -1  -1  -1  -3; ...
                     3  -1   3  -1   1  -3   1   1  -3  -3   3  -3  -1  -1  -1  -1  -1  -3  -3  -1   1   1  -3  -3; ...
                    -3   1  -3   1  -3  -3   1  -3   1  -3  -3  -3  -3  -3   1  -3  -3   1   1  -3   1   1  -3  -3; ...
                    -3  -3   3   3   1  -1  -1  -1   1  -3  -1   1  -1   3  -3  -1  -3  -1  -1   1  -3   3  -1  -3; ...
                    -3  -3  -1  -1  -1  -3   1  -1  -3  -1   3  -3   1  -3   3  -3   3   3   1  -1  -1   1  -3  -3; ...
                     3  -1   1  -1   3  -3   1   1   3  -1  -3   3   1  -3   3  -1  -1  -1  -1   1  -3  -3  -3  -3; ...
                    -3   1  -3   3  -3   1  -3   3   1  -1  -3  -1  -3  -3  -3  -3   1   3  -1   1   3   3   3  -3; ...
                    -3  -1   1  -3  -1  -1   1   1   1   3   3  -1   1  -1   1  -1  -1  -3  -3  -3   3   1  -1  -3; ...
                    -3   3  -1  -3  -1  -1  -1   3  -1  -1   3  -3  -1   3  -3   3  -3  -1   3   1   1  -1  -3  -3; ...
                    -3   1  -1  -3  -3  -1   1  -3  -1  -3   1   1  -1   1   1   3   3   3  -1   1  -1   1  -1  -3; ...
                    -1   3  -1  -1   3   3  -1  -1  -1   3  -1  -3   1   3   1   1  -3  -3  -3  -1  -3  -1  -3  -3; ...
                     3  -3  -3  -1   3   3  -3  -1   3   1   1   1   3  -1   3  -3  -1   3  -1   3   1  -1  -3  -3; ...
                    -3   1  -3   1  -3   1   1   3   1  -3  -3  -1   1   3  -1  -3   3   1  -1  -3  -3  -3  -3  -3; ...
                     3  -3  -1   1   3  -1  -1  -3  -1   3  -1  -3  -1  -3   3  -1   3   1   1  -3   3  -3  -3  -3];
    end

    % Get the phase values specific to group number u from the table of
    % phase values
    phi = phiTable(u+1,:)';

end

function phi = getPhiType2(u)
%   PHI = getPhiType2(U) provides the phase values, PHI, to be applied for
%   generating the type 2 base sequence of length 6 based on the group
%   number U, as stated in the TS 38.211 Section 5.3.2.

    % Table 5.2.3.2-1
    phiTable = [-1 -7 -3 -5 -1  3;...
                -1  3  7 -3  7  3;...
                -1  3  1  5 -1 -5;...
                -7 -3 -7  5 -7 -3;...
                 7  5 -1 -7 -3  1;...
                 3 -3  1  5 -1 -1;...
                -7 -3 -7 -3  7 -5;...
                -7 -3  1 -5 -1 -5;...
                -7 -3  3 -3 -7 -3;...
                -7 -7 -1  1 -5  1;...
                -7 -3 -7  5 -1  5;...
                -7 -7 -3  1  5 -1;...
                 5  7 -3 -5  5 -5;...
                -3  7 -5 -1 -5 -1;...
                 5 -7  7  1  5  1;...
                -7  3  1  5 -1  3;...
                -7 -5 -1 -7 -5  5;...
                -7  1 -3  3  7  5;...
                -7 -7  3  5  1  5;...
                -7 -3  3 -1  3 -5;...
                -7 -5  5  3 -7 -1;...
                 1  5  1  5  3  7;...
                 1 -3  1 -5 -1  3;...
                 1  7  1 -5 -7 -1;...
                 1 -1  3 -1 -7 -3;...
                 1 -1 -5 -1  3 -3;...
                 1 -1  3 -1  3  7;...
                -5  3  7  5  3  7;...
                -7  1 -3  1  5  1;...
                 1  5  3 -7  5 -3];

    % Get the phase values specific to group number u from the table of
    % phase values
    phi = phiTable(u+1,:)';

end

function bits = getBits(u,m)
%   BITS = getBits(U,M) provides the bits values, BITS, to be used for
%   generating the type 2 base sequence based on the group number U and
%   sequence length M, as stated in TS 38.211 Section 5.3.2.

    if m == 12 % Table 5.2.3.2-2
        bitsTable = [0   0   0   0   0   0   1   1   0   1   1   0;...
                     0   0   0   0   0   1   0   0   0   1   1   1;...
                     0	 0   0   0   0   1   1   1   0   1   1   1;...
                     1   1   0   1   1   0   1   0   1   0   0   0;...
                     1   1   0   0   1   0   1   0   1   0   0   1;...
                     1   0   1   1   0   1   0   0   1   0   1   1;...
                     0   0   0   1   0   0   1   0   0   0   1   0;...
                     0   1   0   0   0   1   0   0   1   0   0   0;...
                     1   0   1   1   1   1   0   1   1   0   1   1;...
                     1   0   1   1   0   1   1   1   1   0   0   0;...
                     1   0   1   1   0   1   0   0   0   1   1   0;...
                     1   0   1   0   0   1   0   0   1   0   1   0;...
                     1   1   0   0   0   0   0   1   1   1   1   0;...
                     0   1   0   0   0   1   1   0   1   0   1   1;...
                     0   0   0   0   0   1   1   0   0   0   1   1;...
                     0   0   0   0   0   1   0   0   1   0   0   1;...
                     0   0   1   0   0   1   0   0   0   0   0   1;...
                     0   0   0   0   0   1   1   0   1   1   1   0;...
                     0   0   0   1   1   1   1   1   0   0   0   1;...
                     1   0   0   0   1   0   0   0   0   0   1   1;...
                     0   1   1   1   1   0   1   0   1   1   1   1;...
                     0   1   1   1   0   1   0   0   1   1   0   1;...
                     0   1   1   1   1   1   0   0   1   0   0   0;...
                     0   1   1   1   0   0   0   0   0   1   0   0;...
                     0   0   1   1   1   1   1   1   1   1   0   0;...
                     0   1   1   1   0   0   1   1   0	 1   0   0;...
                     0   1   1   1   0   1   1   1   0   1   1   1;...
                     0   1   1   1   1   1   1   0   0   0   1   1;...
                     0   1   1   1   1   0   0   0   0   0   1   1;...
                     0   1   1   1   0   1   1   1   1   0   1   1];
    elseif m == 18 % Table 5.2.3.2-3
        bitsTable = [0   0   0   0   0   1   0   0   0   1   1   1   1   1   0   0   0   1;...
                     0   0   0   0   0   0   0   1   1   1   1   1   0   0   1   0   0   1;...
                     0   0   0   0   0   1   1   1   1   0   1   1   1   0   1   1   1   1;...
                     0   1   0   1   1   0   1   1   0   0   0   1   1   0   1   0   1   1;...
                     1   1   0   1   0   0   1   0   1   0   1   0   0   1   1   1   1   0;...
                     0   1   0   1   0   1   1   1   0   0   1   0   1   1   0   1   1   0;...
                     0   0   0   1   1   1   0   0   0   1   0   0   0   1   1   1   1   1;...
                     0   1   0   1   0   0   0   1   1   0   1   0   0   0   0   0   1   1;...
                     0   0   1   0   1   0   0   0   1   0   1   0   0   1   0   0   0   1;...
                     1   0   1   1   0   0   1   0   1   0   1   0   0   1   0   0   0   1;...
                     1   0   1   1   0   0   0   1   1   1   0   0   0   0   0   0   0   1;...
                     1   1   0   1   1   0   1   1   1   0   1   1   1   1   1   0   0   0;...
                     1   0   0   0   1   0   1   0   1   0   0   0   1   1   0   1   0   1;...
                     1   0   1   1   0   1   0   1   1   1   0   0   0   0   0   1   1   0;...
                     0   0   0   0   0   1   1   1   0   1   1   0   1   0   1   1   0   0;...
                     0   0   1   1   1   0   1   1   0   1   0   0   0   1   1   0   1   0;...
                     0   1   0   0   1   0   0   0   1   1   1   0   1   0   0   1   1   1;...
                     0   1   0   0   1   1   0   1   1   0   0   0   0   0   0   0   1   0;...
                     0   0   1   0   0   1   1   1   1   0   0   0   0   0   1   1   0   0;...
                     0	 0   0   0   0   0   0   1   0   0   1   0   0   1   1   0   1   1;...
                     0	 0   0   0   0   1   1   0   0   0   0   1   0   0   1   1   1   1;...
                     1	 1   1   1   0   1   0   1   1   1   1   1   0   0   1   0   0   1;...
                     1	 0   0   1   0   0   0   1   0   0   1   1   1   1   0   1   1   1;...
                     0	 0   1   0   0   0   1   1   1   0   0   0   1   0   0   1   0   1;...
                     1	 1   0   1   1   0   0   0   0   0   0   0   1   1   0   1   1   0;...
                     1	 1   0   1   0   1   0   1   1   0   0   0   0   1   0   0   1   0;...
                     0	 1   1   1   1   1   1   1   0   0   1   0   1   0   0   1   0   0;...
                     0	 1   1   0   1   1   1   0   0   0   0   0   0   0   1   1   0   0;...
                     0	 0   0   1   1   0   0   0   0   0   0   0   0   0   1   1   0   0;...
                     0   1   1   1   0   1   1   0   1   0   1   1   1   0   1   1   0   0];
    else % m is equal to 24. Table 5.2.3.2-4
        bitsTable = [0   0   0   0   0   0   0   1   0   0   1   1   1   1   1   0   0   1   0   0   1   0   0   1;...
                     0   0   0   0   0   0   0   1   0   0   1   0   1   1   0   1   1   1   0   0   0   1   1   0;...
                     0   0   0   0   0   0   0   0   1   0   0   1   0   0   1   0   0   1   1   1   1   0   1   1;...
                     0   0   0   0   0   0   0   0   1   1   0   1   1   0   0   1   0   1   0   1   1   0   1   1;...
                     1   0   0   1   1   1   1   1   0   1   1   0   1   1   1   0   1   1   0   0   0   1   1   1;...
                     1   0   1   0   1   1   0   1   1   0   0   1   1   1   1   1   0   0   1   1   0   1   1   1;...
                     0   1   1   0   0   1   0   0   1   1   1   1   1   1   0   1   1   1   1   0   1   1   0   1;...
                     1   0   1   1   1   1   1   1   1   1   1   0   1   0   0   1   1   1   0   0   1   1   0   1;...
                     0   0   1   0   0   1   0   1   0   0   0   1   0   0   1   0   0   0   0   0   1   1   1   0;...
                     0   0   0   0   1   0   0   1   1   0   1   0   0   0   0   0   1   1   0   0   0   1   0   1;...
                     1   0   1   0   0   0   1   1   1   0   0   1   1   1   1   0   1   1   1   1   0   0   1   0;...
                     0   0   1   0   0   1   0   0   0   0   0   1   1   1   0   0   0   1   0   0   1   0   1   0;...
                     1   0   1   0   0   1   1   1   0   1   0   0   0   1   0   1   1   1   0   0   1   0   1   1;...
                     1   0   1   0   0   1   1   0   1   1   0   1   0   1   0   1   1   0   1   1   0   0   1   0;...
                     1   0   1   0   0   0   1   0   0   1   1   1   0   0   0   0   0   1   0   0   1   0   1   1;...
                     1   0   0   1   0   1   0   0   1   1   0   0   0   0   1   1   1   1   1   1   1   0   0   1;...
                     0   0   0   1   1   1   1   0   0   1   0   1   0   0   1   1   1   0   1   1   1   0   0   1;...
                     1   1   0   1   0   1   1   1   0   0   1   1   1   0   0   0   0   0   0   1   1   0   1   0;...
                     0   0   0   0   0   0   0   0   0   1   1   1   1   0   0   0   1   0   1   1   0   0   0   1;...
                     1   0   0   0   1   0   1   1   0   0   0   1   0   0   0   0   0   0   0   0   0   1   1   1;...
                     0   0   0   0   0   0   1   1   1   0   1   1   0   0   0   1   1   0   0   0   1   0   1   0;...
                     0   1   1   0   1   0   1   1   1   0   0   0   0   1   0   0   0   0   1   0   0   0   1   1;...
                     1   0   1   0   0   1   0   0   0   0   0   1   1   1   0   0   1   0   0   0   1   0   1   1;...
                     1   0   0   1   1   0   1   0   0   0   0   0   1   1   1   1   1   1   1   1   0   0   1   1;...
                     1   0   0   0   1   1   0   1   0   1   0   0   1   0   0   1   1   1   1   1   1   0   0   0;...
                     1   0   1   0   1   1   0   0   0   1   0   0   0   1   1   1   1   1   1   0   0   1   0   0;...
                     0   1   0   0   1   0   1   0   1   1   0   0   0   1   1   1   1   1   1   0   0   1   0   0;...
                     0   1   0   1   1   0   1   0   1   0   1   0   1   1   0   1   1   0   0   1   0   0   1   1;...
                     0   1   0   0   0   1   1   0   1   0   1   0   1   1   1   0   1   0   0   1   0   0   1   1;...
                     0   1   0   0   1   0   0   1   1   1   1   1   1   1   1   1   1   0   0   1   0   0   1   1];
    end

    % Get the bit values specific to group number u from the table of
    % bit values
    bits = bitsTable(u+1,:)';

end
